package cn.memset.code.stream;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class ReduceExample {
    public static void main(String[] args) {
        reduceStream();
    }

    public static void reduceStream() {
        Stream<Integer> stream = Stream.of(1, 3, 5, 7, 9);
        Integer sum = stream.reduce((x, y) -> x + y).get();
        System.out.println(sum);
    }

    public static void reduceStream2() {
        List<Integer> list = Arrays.asList(1, 3, 5, 7, 9);

        // 串行执行，对参数 identity 并没有实际的约束。
        Integer sum = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(sum);  // sum = 0+1+3+5+7+9 = 25

        // 串行执行，对参数 identity 并没有实际的约束。
        sum = list.stream().reduce(5, (x, y) -> x + y);
        System.out.println(sum);  // sum = 5+1+3+5+7+9 = 30

        // 并行执行。这是正确的范例：因为数字 0 是累加操作的 identity 。
        sum = list.parallelStream().reduce(0, (x, y) -> x + y);
        System.out.println(sum);  // sum = 0+1+3+5+7+9 = 25

        // 并行执行。这是错误的范例：因为数字 5 并不是累加操作的 identity 。
        sum = list.parallelStream().reduce(5, (x, y) -> x + y);
        System.out.println(sum);  // 会输出一个大于 30 的数字
    }

    public static void reduceStream3() {
        List<String> article = Arrays.asList("hello", "world", "I", "love", "you");
        Integer letterCount = article.stream().reduce(
                0, // identity 初始值　
                (count, str) -> count + str.length(), // accumulator 累加器
                (a, b) -> a + b // combiner 拼接器，并行执行时才会用到
        );

        // 输出 18
        // 5(hello) + 5(world) + 1(I) + 4(love) + 3(you) = 18
        System.out.println(letterCount);
    }

    public static void reduceStream4() {
        List<String> article = Arrays.asList("hello", "world", "I", "love", "you");

        // parallelStream()：以并行的方式执行
        Integer letterCount = article.parallelStream().reduce(
                0, // identity 初始值　
                (count, str) -> count + str.length(), // accumulator 累加器，也起到了 map 的作用
                (a, b) -> a + b // combiner 拼接器，并行执行时才会用到
        );

        // 输出 18
        // 5(hello) + 5(world) + 1(I) + 4(love) + 3(you) = 18
        System.out.println(letterCount);
    }

    public static void reduceStream5() {
        List<String> article = Arrays.asList("hello", "world", "I", "love", "you");

        // parallelStream()：以并行的方式执行
        // 分开的 map + accumulator
        Integer letterCount = article.parallelStream()
                .map(s->s.length())
                .reduce(0, (a, b) -> a + b);

        // 输出 18
        // 5(hello) + 5(world) + 1(I) + 4(love) + 3(you) = 18
        System.out.println(letterCount);
    }
}
